package com.zyl.blog.common.handler;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.core.io.Resource;
import org.springframework.lang.NonNull;
import org.yaml.snakeyaml.Yaml;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;

/**
 * @version v1.0
 * @ProjectName: Personal_Blog_Server
 * @Package: com.zyl.blog.common.handler
 * @ClassName: YamlMessageSource
 * @Description: 修复版：仅扩展YAML解析，复用父类核心逻辑（缓存、编码、并发等）
 * @Author FinalFantasy
 * @Date 2025/9/12-08:50
 */
@Configuration
public class YamlMessageSource extends ReloadableResourceBundleMessageSource {
    // YAML解析器（单例，线程安全）
    private final Yaml yaml = new Yaml();

    // 初始化：让父类支持YAML扩展名（优先加载YAML，再兼容Properties/XML）
    public YamlMessageSource() {
        super();
        // 设置文件扩展名顺序：.yml > .yaml > .properties > .xml
        setFileExtensions(List.of(".yml", ".yaml", ".properties", ".xml"));
    }

    /**
     * 重写父类方法：修复@NonNullApi警告
     * @param resource 资源文件（父类保证非空，故标注@NonNull）
     * @param filename 资源文件名（父类保证非空，故标注@NonNull）
     */
    @NonNull
    @Override
    protected Properties loadProperties(@NonNull Resource resource, @NonNull String filename) throws IOException {
        String resourceName = resource.getFilename();
        // 仅处理YAML文件，其他文件沿用父类逻辑
        if (resourceName != null && (resourceName.endsWith(".yml") || resourceName.endsWith(".yaml"))) {
            return loadYamlProperties(resource);
        }
        return super.loadProperties(resource, filename);
    }

    /**
     * 解析YAML文件为Properties（核心：将YAML层级键转为扁平键，如 system.success）
     */
    private Properties loadYamlProperties(Resource resource) throws IOException {
        Properties properties = new Properties();
        // 读取YAML文件流（复用父类的编码配置）
        try (InputStream inputStream = resource.getInputStream()) {
            // 用SnakeYAML解析YAML为Map（支持嵌套层级）
            Map<String, Object> yamlMap = yaml.loadAs(
                    new InputStreamReader(inputStream, Objects.requireNonNull(getDefaultEncoding())), // 复用父类编码
                    Map.class
            );
            // 将嵌套Map的层级键转为扁平键（如 {system: {success: 操作成功}} → system.success=操作成功）
            flattenYamlMap("", yamlMap, properties);
        }
        return properties;
    }

    /**
     * 递归扁平化YAML嵌套Map：修复未检查转换警告
     * @param prefix 父级键（如 "system"）
     * @param yamlMap 当前层级的YAML Map（键理论上是String，需校验）
     * @param properties 输出的扁平Properties
     */
    private void flattenYamlMap(String prefix, @NonNull Map<?, ?> yamlMap, @NonNull Properties properties) {
        for (Map.Entry<?, ?> entry : yamlMap.entrySet()) {
            // 1. 校验键类型：必须是String（YAML语法要求，避免非法类型）
            if (!(entry.getKey() instanceof String key)) {
                throw new IllegalArgumentException("YAML键必须是String类型，当前类型：" + entry.getKey().getClass().getName());
            }

            // 拼接当前键（父级键+当前键，如 prefix=system → system.success）
            String currentKey = prefix.isEmpty() ? key : prefix + "." + key;
            Object value = entry.getValue();

            // 递归处理嵌套Map，非Map值直接存入Properties
            if (value instanceof Map<?, ?> childMap) {
                // 强制转换为Map<?,?>（已通过instanceof校验，安全）
                flattenYamlMap(currentKey, childMap, properties);
            } else {
                // 处理null值：避免Properties存入"null"字符串（可选，根据业务需求）
                String valueStr = (value == null) ? "" : String.valueOf(value);
                properties.setProperty(currentKey, valueStr);
            }
        }
    }
}